using System;
using System.Threading.Tasks;
using UniversalAdmin.Application.Commands;
using UniversalAdmin.Domain.Entities.App;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Collections.Generic;
using UniversalAdmin.Infrastructure.Data.Contexts;
using Microsoft.EntityFrameworkCore;
using UniversalAdmin.Shared.Enums;

namespace UniversalAdmin.Application.Services
{
    public class AppAuthServices : IAppAuthServices
    {
        private readonly AdminDbContext _db;
        private readonly IAppJwtService _jwtService;
        
        // 锁定配置
        private const int MAX_FAILED_ATTEMPTS = 5; // 最大失败次数
        private const int LOCK_DURATION_MINUTES = 30; // 锁定时间（分钟）
        
        public AppAuthServices(AdminDbContext db, IAppJwtService jwtService)
        {
            _db = db;
            _jwtService = jwtService;
        }

        public async Task<ApiResult> RegisterAsync(string userName, string password, string email)
        {
            // 检查用户名是否已存在
            var exists = _db.AppUsers.Any(u => u.Username == userName);
            if (exists)
                return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "用户名已存在");
            // 生成盐并加密密码
            var salt = Guid.NewGuid().ToString("N");
            var hashPwd = HashPassword(password, salt);
            var user = new AppUser
            {
                Id = Guid.NewGuid(),
                Username = userName,
                Password = hashPwd,
                Email = email,
                Avatar = "default-avatar.png", // 只存储文件名
                Salt = salt,
                AccountStatus = 0,
                FailedLoginAttempts = 0
            };
            // 分配默认普通用户角色
            var defaultRole = _db.AppRoles.FirstOrDefault(r => r.RoleName == "普通用户");
            if (defaultRole == null)
                return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, "系统未配置默认普通用户角色，请联系管理员");
            user.Roles.Add(defaultRole);
            _db.AppUsers.Add(user);
            await _db.SaveChangesAsync();
            return ApiResult.Success("注册成功");
        }

        public async Task<ApiResult> LoginAsync(string userName, string password)
        {
            // 获取用户信息（包括锁定相关字段）
            var user = await _db.AppUsers
                .Where(u => u.Username == userName)
                .FirstOrDefaultAsync();
                
            if (user == null)
                return ApiResult.Failed((int)ApiStatusCode.UNAUTHORIZED, "用户不存在");

            // 检查账户状态
            if (user.AccountStatus == 2)
                return ApiResult.Failed((int)ApiStatusCode.FORBIDDEN, "账号已被管理员禁用");

            // 检查是否被临时锁定
            if (user.AccountStatus == 1)
            {
                if (user.LockedUntil.HasValue && user.LockedUntil.Value > DateTime.UtcNow)
                {
                    var remainingMinutes = (int)Math.Ceiling((user.LockedUntil.Value - DateTime.UtcNow).TotalMinutes);
                    return ApiResult.Failed((int)ApiStatusCode.FORBIDDEN, $"账号已被临时锁定，剩余 {remainingMinutes} 分钟后可重新登录");
                }
                else
                {
                    // 锁定时间已过，重置锁定状态
                    user.AccountStatus = 0;
                    user.FailedLoginAttempts = 0;
                    user.LockedUntil = null;
                    user.LastFailedLogin = null;
                    await _db.SaveChangesAsync();
                }
            }

            // 验证密码
            var hashPwd = HashPassword(password, user.Salt);
            if (user.Password != hashPwd)
            {
                // 密码错误，增加失败次数
                user.FailedLoginAttempts++;
                user.LastFailedLogin = DateTime.UtcNow;
                
                // 检查是否达到最大失败次数
                if (user.FailedLoginAttempts >= MAX_FAILED_ATTEMPTS)
                {
                    user.AccountStatus = 1; // 临时锁定
                    user.LockedUntil = DateTime.UtcNow.AddMinutes(LOCK_DURATION_MINUTES);
                    await _db.SaveChangesAsync();
                    
                    return ApiResult.Failed((int)ApiStatusCode.FORBIDDEN, 
                        $"密码错误次数过多，账号已被临时锁定 {LOCK_DURATION_MINUTES} 分钟");
                }
                
                await _db.SaveChangesAsync();
                
                var remainingAttempts = MAX_FAILED_ATTEMPTS - user.FailedLoginAttempts;
                return ApiResult.Failed((int)ApiStatusCode.UNAUTHORIZED, 
                    $"密码错误，还剩 {remainingAttempts} 次尝试机会");
            }

            // 登录成功，重置失败次数并更新最后登录时间
            user.FailedLoginAttempts = 0;
            user.LastFailedLogin = null;
            user.LockedUntil = null;
            user.AccountStatus = 0;
            user.LastLoginTime = DateTime.UtcNow;
            await _db.SaveChangesAsync();

            // 生成Token
            var accessToken = _jwtService.GenerateAccessToken(user.Id, user.Username);
            var refreshToken = _jwtService.GenerateRefreshToken();
            
            // 获取用户角色
            var roles = await _db.AppUsers
                .Where(u => u.Id == user.Id)
                .SelectMany(u => u.Roles)
                .Select(r => r.RoleName)
                .ToListAsync();
                
            var userInfo = new {
                userId = user.Id,
                userName = user.Username,
                avatar = user.Avatar,
                roles = roles
            };
            var data = new Dictionary<string, object>
            {
                { "accessToken", accessToken },
                { "refreshToken", refreshToken },
                { "userInfo", userInfo }
            };
            return ApiResult.Success("登录成功", data);
        }

        private static string HashPassword(string password, string salt)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(password + salt);
            byte[] hash = SHA256.HashData(bytes);
            return Convert.ToBase64String(hash);
        }
    }
} 